﻿using System;
using System.Drawing;
using System.Threading;
using MDK.Device.Devices;
using System.Linq;
using System.Reflection;
using MDK.Common;
using MDK.Device.Components;
using MDK.Device.Helper;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Speech.Synthesis;
using MDK.Model.Models;
using MDK.Common.Helper;

namespace MDK.Device
{
    public class Flow
    {
        private string _taskId { get; set; }

        public PositionModel PosModel { get; private set; }

        public SystemModel SysModel { get; private set; }

        public bool IsRunning { get; private set; }

        public bool IsDebugMode { get; private set; }

        public SpeechSynthesizer Speech { get; private set; }
        /// <summary>
        /// 离心机配置
        /// </summary>
        public T_CentrifugeSetting _CentrifugeSetting { get; private set; }

        public void Initialize()
        {
            SysModel.Atm.Device.PLC.Open();
            SysModel.Front.Device.PLC.Open();
            SysModel.Back.Device.PLC.Open();

            SysModel.Atm.Device.SwitchAutoMode();
            SysModel.Front.Device.SwitchAutoMode();
            SysModel.Back.Device.SwitchAutoMode();
            SysModel.Atm.Device.ClearError();
            SysModel.Front.Device.ClearError();
            SysModel.Back.Device.ClearError();

            SysModel.Back.Lamp.TurnOn();
            SysModel.Front.Lamp.TurnOn();


            SysModel.Back.Belt.Stop();
            SysModel.Atm.Belt.Stop();
            SysModel.Atm.AtmCamerePower.TurnOff();
            SysModel.Atm.CarmeraDamBoard.StartRecede();
            SysModel.Atm.CrossingPushrod.StartRecede();
            SysModel.Atm.CrossingDamBoard.StartForward();

            while (SysModel.Atm.BeltStartSensor.IsActive())
            {
                SpeechHelper.SpeekAynsc("ATM异物入侵");
                Thread.Sleep(3000);
            }
            SysModel.Atm.Door.StartForward();

            SysModel.Atm.CarmeraDamBoard.WaitCompleted();
            SysModel.Atm.CrossingPushrod.WaitCompleted();
            SysModel.Atm.CarmeraDamBoard.WaitCompleted();
            SysModel.Atm.Door.WaitCompleted();

            SysModel.Back.X.Speed = 1000;
            SysModel.Back.Y.Speed = 1000;
            SysModel.Front.X.Speed = 1000;
            SysModel.Front.Y.Speed = 1000;
            SysModel.Front.Z.Speed = 1000;

        }

        public Flow()
        {
            Speech = new SpeechSynthesizer();
            var voice = Speech.GetInstalledVoices(CultureInfo.GetCultureInfo("zh-CN"));
            if (voice.Count >= 1)
            {
                Speech.SelectVoice(voice[0].VoiceInfo.Name);
            }
            CentrifugePeriod = TimeSpan.FromSeconds(10);//TimeSpan.FromMinutes(10);

            PosModel = PositionModel.Load();
            SysModel = SystemModel.Instance;
            _IsTaskOk = true;
        }

        #region 对外接口

        /// <summary>
        /// 初始化，new对象之后调用，只调用一次
        /// </summary>
        public void Start(bool debug = false)
        {
            IsRunning = true;

            IsDebugMode = debug;
            if (!debug)
            {
                SysModel.Front.RasterSwitch.TurnOn();
            }

            Initialize();

            // 启动任务
            var tasks = GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public).Where(t => t.Name.EndsWith("Task")).ToArray();
            foreach (var task in tasks)
            {
                ThreadPool.QueueUserWorkItem(obj =>
                {
                    try
                    {
                        Thread.CurrentThread.Name = obj.ToString();
                        task.Invoke(this, new object[0]);
                    }
                    catch (Exception e)
                    {
                        File.WriteAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "error.log"), e.ToString());
                    }
                }, task.Name);
            }
        }

        /// <summary>
        /// 反初始化,程序关闭的时候调用
        /// </summary>
        public void Stop()
        {

        }

        /// <summary>
        /// 当前交接单ID,未null时表示无交接单
        /// </summary>
        public string CurrentHandoverId { get; private set; }

        public bool IsHandover { get; private set; }
        /// <summary>
        /// 任务是否完成
        /// </summary>
        public bool _IsTaskOk { get; private set; }
        /// <summary>
        /// 开始交接,调用之后开门
        /// </summary>
        /// <param name="handoverId">交接单Id</param>
        /// <param name="needCentrifuge">是否需要离心</param>
        /// <param name="priority">是否需要优先处理</param>
        /// <returns>返回false则不能交接(不会开门)</returns>
        public bool BeginHandover(string handoverId, bool needCentrifuge, bool priority)
        {
            if (!string.IsNullOrWhiteSpace(handoverId) && string.IsNullOrWhiteSpace(CurrentHandoverId) && !SysModel.Atm.BeltStartSensor.IsActive())
            {
                IsHandover = true;
                _timestamp = DateTime.Now;
                CurrentHandoverId = handoverId;
                _curHandoverNeedCentrifuge = needCentrifuge;
                _curHandoverPriority = priority;
                SysModel.Atm.Lamp.TurnOn();
                SysModel.Atm.Door.StartRecede();
                return true;
            }
            return false;
        }

        /// <summary>
        /// 结束交接(关门)
        /// </summary>
        public void EndHandover()
        {
            SysModel.Atm.Lamp.TurnOff();
            while (SysModel.Atm.BeltStartSensor.IsActive())
            {
                Thread.Sleep(10);
            }
            SysModel.Atm.Door.StartForward();
            IsHandover = false;
        }

        public TimeSpan CentrifugePeriod { get; set; }

        /// <summary>
        /// 开始转移到黑色试管架
        /// </summary>
        /// <param name="_taskId">任务ID</param>
        /// <param name="tubeType">样本类型</param>
        /// <param name="expectCount">期望上机（上载条）的试管数量，最终实际上载条的数量可能会因为某些原因导致少于期望的数量</param>
        public void BeginTransferToAusbio(string _taskId, int tubeType, int expectCount)
        {
            _taskTubeCount = BeginHandle(_taskId, tubeType, expectCount, PalletStatus.WaitToAusbio);
        }

        /// <summary>
        /// 开始转移到白色试管架
        /// </summary>
        /// <param name="_taskId">任务ID</param>
        /// <param name="tubeType">样本类型</param>
        /// <param name="expectCount">期望上机（上载条）的试管数量，最终实际上载条的数量可能会因为某些原因导致少于期望的数量</param>
        public void BeginTransferToTecen(string _taskId, int tubeType, int expectCount)
        {
            _taskTubeCount = BeginHandle(_taskId, tubeType, expectCount, PalletStatus.WaitToTecen);
        }

        /// <summary>
        /// 开始转移到绿色试管架
        /// </summary>
        /// <param name="_taskId">任务ID</param>
        /// <param name="tubeType">样本类型</param>
        /// <param name="expectCount">期望上机（上载条）的试管数量，最终实际上载条的数量可能会因为某些原因导致少于期望的数量</param>
        public void BeginTransferToBackman(string _taskId, int tubeType, int expectCount)
        {
            _taskTubeCount = BeginHandle(_taskId, tubeType, expectCount, PalletStatus.WaitToBackman);
        }

        public bool IsWaitManualHandle { get; private set; }
        public bool IsManualHandle { get; private set; }

        public bool BeginManaulHandle(bool IsWait = true)
        {
            if (IsManualHandle) return true;
            if (IsWait)
            {
                _handleLock.Reset();
                IsWaitManualHandle = true;
                while (IsWaitManualHandle)
                {
                    if (_handleLock.WaitOne(0))
                    {
                        SysModel.Front.RasterSwitch.TurnOff();
                        IsManualHandle = true;
                        return true;
                    }
                    Thread.Sleep(300);
                }
            }
            else
            {
                SysModel.Front.RasterSwitch.TurnOff();
                IsManualHandle = true;
                return true;
            }
            return false;
        }

        public void EndManaulHandle()
        {
            if (!IsDebugMode)
            {
                SysModel.Front.RasterSwitch.TurnOn();
            }
            IsWaitManualHandle = false;
            IsManualHandle = false;
        }

        private void WaitManaulHandle()
        {
            if (IsWaitManualHandle)
            {
                _handleLock.Set();
                while (IsWaitManualHandle)
                {
                    Thread.Sleep(300);
                }
            }
        }

        #endregion

        #region 微任务

        private readonly MultipleLock _atmBeltLock = new MultipleLock();
        private readonly AutoResetEvent _freezerLock = new AutoResetEvent(true);

        private bool _curHandoverNeedCentrifuge = false;
        private bool _curHandoverPriority = false;
        private DateTime _lastBalanceTimestamp = DateTime.Now;

        private TimeSpan _handoverTimeout = TimeSpan.FromSeconds(30);
        DateTime _timestamp = DateTime.Now;
        /// <summary>
        /// 循环读取Atm皮带起点状态,上升沿扫码,扫码成功后加入
        /// </summary>
        private void AtmScanTask()
        {
            while (IsRunning)
            {
                try
                {
                    if (IsHandover)
                    {
                        if (SysModel.Atm.BeltStartSensor.IsActive(20))
                        {
                            _timestamp = DateTime.Now;
                            SysModel.Atm.CrossingDamBoard.StartForward();
                            SysModel.Atm.CrossingDamBoard.WaitCompleted();
                            SysModel.Atm.CrossingPushrod.StartRecede();
                            SysModel.Atm.CrossingPushrod.WaitCompleted();
                            SysModel.Atm.Belt.StartForward();
                        }
                        if (DateTime.Now - _timestamp > _handoverTimeout && SysModel.Atm.BeltCorrelation.IsActive(20))
                        {
                            FlowEventHelper.EndHandover();
                            SysModel.Atm.Belt.Stop();
                            _timestamp = DateTime.Now;
                        }
                    }
                    Thread.Sleep(50);
                }
                catch
                {

                }
            }
        }
        private void FreezerTransportTask()
        {
            while (IsRunning)
            {
                if (PosModel.FreezerBeltPosition.Pallet != null && PosModel.FreezerBeltPosition.Pallet.State == PalletStatus.WaitToFreezer)
                {
                    // TODO: 离心托扫码
                    PosModel.FreezerBeltPosition.Pallet.ActiveBarcode = "";//先清空条码  防止试管位置旋转
                    PosModel.FreezerBeltPosition.Pallet.ActiveBarcode = "TEST01";

                    var targetAisle = PosModel.AllocFreezerAisleForIn(PosModel.FreezerBeltPosition.Pallet.Type);
                    if (targetAisle >= 0)
                    {
                        SysModel.Freezer.Pushrods[targetAisle].StartRecede();
                        for (int i = 0; i <= targetAisle; i++)
                        {
                            SysModel.Freezer.DamBoards[i].StartRecede();
                        }

                        if (targetAisle < 5)
                        {
                            SysModel.Freezer.DamBoards[targetAisle + 1].StartForward();
                        }
                        SysModel.Freezer.Belt.StartRecede();
                        for (int i = 0; i <= targetAisle; i++)
                        {
                            SysModel.Freezer.DamBoards[i].WaitCompleted();
                        }
                        while (!SysModel.Freezer.DamBoardSensors[targetAisle].IsActive())
                        {
                            Thread.Sleep(10);
                        }
                        Thread.Sleep(1000);
                        SysModel.Freezer.Belt.Stop();
                        SysModel.Freezer.DamBoards[0].StartForward();
                        if (targetAisle != 0)
                        {
                            SysModel.Freezer.DamBoards[targetAisle].StartForward();
                        }
                        SysModel.Freezer.DamBoards[targetAisle].WaitCompleted();
                        SysModel.Freezer.Pushrods[targetAisle].WaitCompleted();

                        PosModel.FreezerBeltPosition.Pallet.State = PalletStatus.Storage;
                        PosModel.FreezerPositions[targetAisle].Push(PosModel.FreezerBeltPosition.Pallet);
                        //更新冷藏工位
                        PosModel.FreezerPositionChanged(targetAisle);

                        var startFreezerTime = DateTime.Now;
                        var historys = PosModel.FreezerBeltPosition.Pallet.Tubes
                                .Select(s => new T_HistorySample
                                {
                                    Id = Guid.NewGuid().ToString("N"),
                                    SampleId = s.Id,
                                    Time = startFreezerTime,
                                    Remark = "进入冷藏"
                                }).ToArray();
                        foreach (var history in historys)
                        {
                            IDatatoFlow.InsertSampleHistory(history);
                        }

                        PosModel.FreezerBeltPosition.Pallet = null;
                    }
                }

                var maxAisle = -1;
                for (int i = PosModel.FreezerPositions.Length - 1; i >= 0; i--)
                {
                    if (PosModel.FreezerPositions[i].Any(t => t.State == PalletStatus.WaitToAusbio || t.State == PalletStatus.WaitToTecen || t.State == PalletStatus.WaitToBackman || t.State == PalletStatus.WaitToDesktop))
                    {
                        if (maxAisle < 0)
                        {
                            maxAisle = i;

                            for (int aisle = 0; aisle <= maxAisle; aisle++)
                            {
                                SysModel.Freezer.DamBoards[aisle].StartRecede();
                            }
                            for (int aisle = 0; aisle <= maxAisle; aisle++)
                            {
                                SysModel.Freezer.DamBoards[aisle].WaitCompleted();
                            }
                        }

                        while (PosModel.FreezerPositions[i].Any(t => t.State != PalletStatus.Storage))
                        {
                            _IsDetrusion = true;
                            while (_IsOkGrasped)
                            {
                                Thread.Sleep(10);
                            }
                            _freezerLock.WaitOne();
                           
                            SysModel.Freezer.Belt.StartForward();

                            while (SysModel.Freezer.BeltCenterSensor.IsActive())
                            {
                                Thread.Sleep(10);
                            }
                            SysModel.Freezer.Pushrods[i].StartForward();
                            while (!SysModel.Freezer.DamBoardSensors[i].IsActive())
                            {
                                Thread.Sleep(10);
                            }
                            SysModel.Freezer.Pushrods[i].Stop();

                            var pallet = PosModel.FreezerPositions[i].Pop();

                            if (pallet.State == PalletStatus.Storage)
                            {
                                pallet.State = PalletStatus.WaitToDesktop;
                            }

                            var endFreezerTime = DateTime.Now;
                            var historys = pallet.Tubes
                                .Select(s => new T_HistorySample
                                {
                                    Id = Guid.NewGuid().ToString("N"),
                                    SampleId = s.Id,
                                    Time = endFreezerTime,
                                    Remark = "推出冷藏"
                                }).ToArray();
                            foreach (var history in historys)
                            {
                                IDatatoFlow.InsertSampleHistory(history);
                            }

                            PosModel.FreezerBeltPalletQueue.Enqueue(pallet);

                            while (!SysModel.Freezer.BeltCenterSensor.IsActive())
                            {
                                Thread.Sleep(10);
                            }

                            //更新冷藏工位
                            PosModel.FreezerPositionChanged(i);
                            _freezerLock.Set();
                            _IsOkGrasped = true;

                        }
                        _IsDetrusion = false;
                    }
                }

                if (maxAisle >= 0)
                {
                    SysModel.Freezer.Pushrods[0].StartRecede();
                    SysModel.Freezer.DamBoards[0].StartForward();
                }

                Thread.Sleep(300);
            }
        }

        private int[] _scanPath = { 13, 14, 15, 10, 6, 5, 4, 9, 12, 17, 18, 19, 16, 11, 7, 2, 1, 0, 3, 8 };
        bool _IsATMStartStop = true;
        bool _IsHaveSupport = false;
        bool _IsDetrusion = false;
        /// <summary>
        /// 是否可以抓取
        /// </summary>
        bool _IsOkGrasped = false;
        private void FrontTask()
        {
            string[] curCenId = new string[2];
            DateTime lastAtmInTime = DateTime.MinValue;
            while (IsRunning)
            {
                #region ATM => 台面 || 后处理 => 台面

                if (!IsHandover)
                {
                    while (!SysModel.Atm.BeltCorrelation.IsActive(20,false))
                    {
                        _IsHaveSupport = true;
                        if (_IsATMStartStop)
                        {
                            _IsATMStartStop = false;
                            lastAtmInTime = DateTime.Now;
                            SysModel.Atm.Belt.StartForward();
                        }
                        while (SysModel.Atm.BeltEndSensor.IsActive(20))
                        {
                            
                            // 找目标位
                            var target = PosModel.AllocFreePosition(SysModel);

                            if (target == null)
                            {
                                BeginManaulHandle(false);
                                FlowEventHelper.SendMessage(new HandoverStateChangedArgs() { Code = FlowMesssages.FrontPositionUseUp, Detail = "台面工位耗尽", Message = "台面工位全部耗尽，请人工处理,清空台面空托" }, SysModel);
                                break;
                            }

                            PosModel.AtmBeltPosition.Pallet = new Pallet()
                            {
                                NeedCentrifuge = _curHandoverNeedCentrifuge,
                                HandoverId = CurrentHandoverId
                            };

                            // 抓托, 托状态不变
                            SysModel.FrontDragPallet(PosModel.AtmBeltPosition, target,
                                doAfterDrag: () =>
                                {
                                    _IsATMStartStop = false;
                                    lastAtmInTime = DateTime.Now;
                                    SysModel.Atm.Belt.StartForward();
                                }, 
                                doAfterDrop:()=>
                                {
                                    SysModel.Atm.Belt.Stop();
                                    Thread.Sleep(500);
                                }
                                );
                            _IsHaveSupport = false;
                        }
                        // Thread.Sleep(100);
                        if (lastAtmInTime != DateTime.MinValue && SysModel.Atm.BeltCorrelation.IsActive(200) && !_IsHaveSupport)
                        {
                            Thread.Sleep(2000);//对射开关有时感应不到  延时保证托到位
                            _IsATMStartStop = true;
                            SysModel.Atm.Belt.Stop();
                            lastAtmInTime = DateTime.MinValue;
                        }

                    }
                    CurrentHandoverId = null;
                }

                #endregion

                WaitManaulHandle();

                #region 处理待配平队列

                // 配平周期到 || 待配平试管超过80根
                var cenTick = (DateTime.Now - _lastBalanceTimestamp > CentrifugePeriod) && PosModel.DesktopPositions.Any(t => t.Pallet != null && t.Pallet.State == PalletStatus.WaitBalance);
                var waitBalanceTubeGt80 = PosModel.DesktopPositions.Where(t => t.Pallet != null && t.Pallet.State == PalletStatus.WaitBalance && string.IsNullOrEmpty(t.Pallet.GroupId)).Select(t => t.Pallet.Tubes.Count(s => s.Type != TubeTypes.None)).Count() >= 80;
                if ((cenTick || waitBalanceTubeGt80) && PosModel.CameraToFrontPalletQueue.IsEmpty)
                {
                    _lastBalanceTimestamp = DateTime.Now;

                    var balance = PosModel.DesktopPositions.Where(t => t.Pallet != null && t.Pallet.State == PalletStatus.WaitBalance).ToList();
                    if (balance.Sum(t => t.Pallet.TubeCount) <= 0)//空托不配平，改变空托状态
                    {
                        foreach (var item in balance)
                            item.Pallet.State = PalletStatus.WaitToFreezer;
                    }
                    else
                    {


                        // 试管分组
                        var tubeCount = 0;
                        var groupPositions = PosModel.GroupTubeForCentrifuge(out tubeCount,SysModel, delegate
                        {
                            BeginManaulHandle(false);
                        }, SysModel.Atm.BeltCorrelation.IsActive(20));

                        if (groupPositions != null)
                        {
                            var groupId = Guid.NewGuid().ToString("N");
                            groupPositions[0].Pallet.GroupId = groupPositions[1].Pallet.GroupId = groupPositions[2].Pallet.GroupId = groupPositions[3].Pallet.GroupId = groupId;
                            groupPositions[0].Pallet.GroupIndex = 0;
                            groupPositions[1].Pallet.GroupIndex = 1;
                            groupPositions[2].Pallet.GroupIndex = 2;
                            groupPositions[3].Pallet.GroupIndex = 3;
                            var sumLayout = new int[4];
                            sumLayout[0] = sumLayout[2] = tubeCount % 4 == 0 ? (tubeCount / 4) : (tubeCount / 4 + 1);
                            sumLayout[1] = sumLayout[3] = (tubeCount % 4) > 2 ? (tubeCount / 4 + 1) : (tubeCount / 4);

                            var startBalanceTime = DateTime.Now;

                            for (int i = 0; i < 4; i++)
                            {
                                var blc = Centrifuge.GetBalanceCode(sumLayout[i]);
                                for (int j = 0; j < 20; j++)
                                {
                                    if (((blc >> j) & 1) != 0)
                                    {
                                        if (groupPositions[i].Pallet.Tubes[j].Type == TubeTypes.None)
                                        {
                                            var clamped = false;
                                            for (int k = 0; k < groupPositions.Count; k++)
                                            {
                                                var tblc = k < 4 ? Centrifuge.GetBalanceCode(sumLayout[k]) : Centrifuge.GetBalanceCode(0);
                                                for (int l = 0; l < 20; l++)
                                                {
                                                    if (((tblc >> l) & 1) == 0 && groupPositions[k].Pallet.Tubes[l].Type != TubeTypes.None)
                                                    {
                                                        SysModel.FrontDragTube(groupPositions[k], l, groupPositions[i], j);

                                                        clamped = true;
                                                        break;
                                                    }
                                                }
                                                if (clamped)
                                                {
                                                    break;
                                                }
                                            }

                                            if (!clamped)
                                            {
                                                int balanceHole;
                                                var from = PosModel.AllocBalanceTube(out balanceHole);
                                                SysModel.FrontDragTube(from, balanceHole, groupPositions[i], j);
                                            }
                                        }
                                    }
                                }

                                groupPositions[i].Pallet.State = PalletStatus.WaitCentrifuge;
                                groupPositions[i].Pallet.GroupIndex = i;
                            }

                            for (int i = 4; i < groupPositions.Count; i++)
                            {
                                groupPositions[i].Pallet.GroupId = null;
                            }

                            var endBalanceTime = DateTime.Now;

                            var historys = groupPositions.Where(t => !string.IsNullOrWhiteSpace(t.Pallet.GroupId))
                                .SelectMany(t => t.Pallet.Tubes.Where(s => s.Type != TubeTypes.None)
                                    .SelectMany(s => new[]
                                    {
                                    new T_HistorySample
                                    {
                                        Id = Guid.NewGuid().ToString("N"),
                                        SampleId = s.Id,
                                        Time = startBalanceTime,
                                        Remark = "开始配平"
                                    },
                                    new T_HistorySample
                                    {
                                        Id = Guid.NewGuid().ToString("N"),
                                        SampleId = s.Id,
                                        Time = endBalanceTime,
                                        Remark = "完成配平"
                                    },
                                    })).ToArray();
                            foreach (var history in historys)
                            {
                                IDatatoFlow.InsertSampleHistory(history);
                            }

                            SysModel.Front.Z.Goto(0);
                            SysModel.Front.SZ.Goto(0);
                            SysModel.Front.Z.WaitCompleted();
                            SysModel.Front.SZ.WaitCompleted();
                        }
                    }
                }
                #endregion

                WaitManaulHandle();

                #region 台面 => 离心机

                var group = PosModel.AllocCentrifugeGroup();
                if (group != null)
                {
                    if (group.Sum(t => t.Pallet.TubeCount) <= 0)//空托不离心
                    {
                        foreach (var item in group)
                            item.Pallet.State = PalletStatus.WaitToFreezer;
                    }
                    else
                    {

                        var cenIndex = SysModel.AllocCentrifuge();

                        if (cenIndex >= 0)
                        {
                            SysModel.Centrifuges[cenIndex].UseCount++;
                            SysModel.Centrifuges[cenIndex].IsFree = false;
                            //先回原点，延迟6s
                            SysModel.Centrifuges[cenIndex].GotoStation(0);
                            Thread.Sleep(6000);

                            SysModel.Centrifuges[cenIndex].StartOpenDoor();


                            while (SysModel.Centrifuges[cenIndex].GetDoorState() != CentrifugeDoorLocations.Opened)
                            {
                                Thread.Sleep(100);
                            }
                            foreach (var position in group)
                            {
                                SysModel.Centrifuges[cenIndex].GotoStation(position.Pallet.GroupIndex + 1);
                                SysModel.FrontDragPallet(position, PosModel.CentrifugePositions[cenIndex][position.Pallet.GroupIndex],
                                    doAfterDrag: () =>
                                    {
                                        while (SysModel.Centrifuges[cenIndex].GetStation() != (position.Pallet.GroupIndex + 1) || SysModel.Centrifuges[cenIndex].GetDoorState() != CentrifugeDoorLocations.Opened)
                                        {
                                            Thread.Sleep(100);
                                        }
                                    });
                            }
                            SysModel.Centrifuges[cenIndex].StartCloseDoor();
                            while (SysModel.Centrifuges[cenIndex].GetDoorState() != CentrifugeDoorLocations.Closed)
                            {
                                Thread.Sleep(100);
                            }
                            _CentrifugeSetting = IDatatoFlow.GetCentrifugeSetting();
                            SysModel.Centrifuges[cenIndex].Speed = Convert.ToInt32(_CentrifugeSetting.CentrifugeSpeed);
                            SysModel.Centrifuges[cenIndex].RunTime = Convert.ToInt32(_CentrifugeSetting.CentrifugeTime);
                            SysModel.Centrifuges[cenIndex].Balance = Convert.ToInt32(_CentrifugeSetting.CentrifugeNoBalance);
                            SysModel.Centrifuges[cenIndex].Temperature = Convert.ToInt32(_CentrifugeSetting.CentrifugeTemperature);
                            SysModel.Centrifuges[cenIndex].Begin();

                            var startCenTime = DateTime.Now;

                            var tc = new T_Centrifuge
                            {
                                Id = Guid.NewGuid().ToString("N"),
                                CentrifugeName = cenIndex == 0 ? "左离心机" : "右离心机",
                                StartTime = startCenTime,
                                CentrifugeState = "开始离心"
                            };
                            curCenId[cenIndex] = tc.Id;
                            IDatatoFlow.CentrifugeInsert(tc,
                                PosModel.CentrifugePositions[cenIndex].SelectMany(t => t.Pallet.Tubes.Where(s => s.Type != TubeTypes.None).Select(s => s.Id)).ToArray());

                            var historys = PosModel.CentrifugePositions[cenIndex].Where(t => !string.IsNullOrWhiteSpace(t.Pallet.GroupId))
                                .SelectMany(t => t.Pallet.Tubes.Where(s => s.Type != TubeTypes.None)
                                    .Select(s => new T_HistorySample
                                    {
                                        Id = Guid.NewGuid().ToString("N"),
                                        SampleId = s.Id,
                                        Time = startCenTime,
                                        Remark = "开始离心"
                                    })).ToArray();
                            foreach (var history in historys)
                            {
                                IDatatoFlow.InsertSampleHistory(history);
                            }
                        }
                    }

                }
                #endregion

                WaitManaulHandle();

                #region 离心机 => 台面

                for (int i = 0; i < 2; i++)
                {
                    if (SysModel.Centrifuges != null && SysModel.Centrifuges[i].IsFree == false && SysModel.Centrifuges[i].CurrentState == CentrifugeStatus.Stop && SysModel.Centrifuges[i].SurplusTime == 0)
                    {
                        SysModel.Centrifuges[i].StartOpenDoor();
                        while (SysModel.Centrifuges[i].GetDoorState() != CentrifugeDoorLocations.Opened)
                        {
                            Thread.Sleep(100);
                        }
                        //先回原点，延迟6秒
                        SysModel.Centrifuges[i].GotoStation(0);
                        Thread.Sleep(6000);

                        var targetList = new List<Position>();
                        for (int j = 0; j < 4; j++)
                        {
                            SysModel.Centrifuges[i].GotoStation(j + 1);
                            var target = PosModel.AllocFreePosition(SysModel);
                            if (target != null)
                            {
                                SysModel.FrontDragPallet(PosModel.CentrifugePositions[i][j], target,
                                    doBeforeDrag: () =>
                                    {
                                        while (SysModel.Centrifuges[i].GetStation() != (j + 1) || SysModel.Centrifuges[i].GetDoorState() != CentrifugeDoorLocations.Opened)
                                        {
                                            Thread.Sleep(100);
                                        }
                                    }, IsEarlierY: true);

                                target.Pallet.State = PalletStatus.WaitToFreezer;
                                target.Pallet.GroupId = null;
                                targetList.Add(target);
                            }
                        }
                        SysModel.Centrifuges[i].StartCloseDoor();
                        // SysModel.Centrifuges[i].TurnOffCompressor();
                        SysModel.Centrifuges[i].IsFree = true;

                        IDatatoFlow.CentrifugeCompleted(curCenId[i]);
                        curCenId[i] = null;
                        var endCenTime = DateTime.Now;
                        var historys = targetList.Where(t => !string.IsNullOrWhiteSpace(t.Pallet.GroupId))
                            .SelectMany(t => t.Pallet.Tubes.Where(s => s.Type != TubeTypes.None)
                                .Select(s => new T_HistorySample
                                {
                                    Id = Guid.NewGuid().ToString("N"),
                                    SampleId = s.Id,
                                    Time = endCenTime,
                                    Remark = "完成离心"
                                })).ToArray();
                        foreach (var history in historys)
                        {
                            IDatatoFlow.InsertSampleHistory(history);
                        }
                    }
                }

                #endregion

                WaitManaulHandle();

                #region 移除配平管

                while (true)
                {
                    int fromHole, toHole;
                    Position from = null, to = null;

                    // 移除所有配平管
                    from = PosModel.CollectBalanceTube(out fromHole);
                    if (from != null)
                    {
                        to = PosModel.AllocEmptyHole(TubeTypes.Balance, out toHole);
                        SysModel.FrontDragTube(from, fromHole, to, toHole);
                    }
                    else
                    {
                        break;
                    }
                }

                #endregion

                WaitManaulHandle();

                #region 冷藏 => 台面

                if (PosModel.CameraToFrontPalletQueue.IsEmpty)
                {
                    while (_IsDetrusion || _IsOkGrasped)
                    {
                        if (!PosModel.FreezerBeltPalletQueue.IsEmpty && SysModel.Freezer.BeltEndSensor.IsActive())
                        {
                            var target = PosModel.AllocFreePosition(SysModel);
                            if (target != null)
                            {
                                Pallet pallet;
                                PosModel.FreezerBeltPalletQueue.TryDequeue(out pallet);
                                PosModel.FreezerBeltPosition.Pallet = pallet;

                                // TODO: 离心托扫码
                                PosModel.FreezerBeltPosition.Pallet.ActiveBarcode = "TEST02";
                                SysModel.FrontDragPallet(PosModel.FreezerBeltPosition, target, doAfterDrop: () =>
                                {
                                    SysModel.Freezer.Belt.Stop();
                                    Thread.Sleep(500);
                                });
                                if (target.Pallet.State == PalletStatus.WaitToDesktop) target.Pallet.State = PalletStatus.WaitToFreezer;
                            }
                            _IsOkGrasped = false;
                        }

                    }
                   
                }

                #endregion

                WaitManaulHandle();

                #region 处理待扫码队列
                while (PosModel.CameraToFrontPalletQueue.IsEmpty)
                {
                    var position = PosModel.DesktopPositions.FirstOrDefault(t =>
                        t.Pallet != null && t.Pallet.State == PalletStatus.WaitScanBarcode);
                    if (position != null)
                    {

                        SysModel.Front.Finger.TurnOn();
                        SysModel.Front.Z.Goto(0);
                        SysModel.Front.SZ.Goto(0);
                        SysModel.Front.Z.WaitCompleted();
                        SysModel.Front.SZ.WaitCompleted();

                        for (int i = 0; i < position.Pallet.Tubes.Length; i++)
                        {
                            if (!string.IsNullOrWhiteSpace(position.Pallet.Tubes[_scanPath[i]].Barcode)) continue;

                            SysModel.ScanFrontDragTube(position, _scanPath[i],
                                doAfterDrag: () =>
                                {
                                    var tube = position.Pallet.Tubes[_scanPath[i]];

                                    tube.GatherTime = DateTime.Now;
                                    //TODO: 扫码
                                    SysModel.Front.FingerScanner.Trigger();
                                    tube.Barcode = SysModel.Front.FingerScanner.WaitCompleted();
                                    SysModel.Front.FingerScanner.Cancel();

                                    if (!string.IsNullOrEmpty(tube.Barcode))
                                    {
                                        var item= SampleResultApi.GetDonorInfo(tube.Barcode);
                                        if (item != null)
                                        {
                                            tube.BloodType = item.PstABO;
                                            tube.GatherTime = item.CollectDate;
                                        }
                                    }
                                    else
                                    {
                                        tube.Barcode = "NoCode";//TODO: 未扫到条码
                                    }

                                    tube.Id = Guid.NewGuid().ToString("N");

                                    IDatatoFlow.SampleInsert(new T_Sample
                                    {
                                        Id = tube.Id,
                                        HandId = position.Pallet.HandoverId,
                                        DonCode = tube.Barcode,
                                        ABO = tube.BloodType,
                                        SampleType = (int)TubeTypes.Meimian,
                                        PostionId = position.Id,
                                        GatherTime = tube.GatherTime,
                                        Is_Delete = false,
                                        Index = _scanPath[i],
                                        State = 0
                                    });
                                });
                        }

                        SysModel.Front.Finger.TurnOn();
                        SysModel.Front.Z.Goto(0);
                        SysModel.Front.SZ.Goto(0);
                        SysModel.Front.Z.WaitCompleted();
                        SysModel.Front.SZ.WaitCompleted();

                        if (position.Pallet.NeedCentrifuge && position.Pallet.TubeCount > 0)
                            position.Pallet.State = PalletStatus.WaitBalance;
                        else
                            position.Pallet.State = PalletStatus.WaitToFreezer;
                    }
                    else
                    {
                        break;
                    }


                }
                #endregion

                WaitManaulHandle();

                #region 处理待分拣队列

                if (PosModel.CameraToFrontPalletQueue.IsEmpty)
                {
                    foreach (var from in PosModel.DesktopPositions)
                    {
                        if (from.Pallet == null
                            || from.Pallet.State != PalletStatus.WaitToFreezer
                            || from.Pallet.Type != TubeTypes.Mixed)
                        {
                            continue;
                        }

                        for (int fromHole = 0; fromHole < 20; fromHole++)
                        {
                            if (from.Pallet.Tubes[fromHole].Type == TubeTypes.None || from.Pallet.Tubes[fromHole].Type == from.Pallet.ExceptType) continue;
                            var to = PosModel.DesktopPositions
                                         .Where(t => t.Pallet != null && (t.Pallet.ExceptType == @from.Pallet.Tubes[fromHole].Type && t.Pallet.EmptyHoleCount > 0))
                                         .OrderByDescending(t => t.Pallet.ExceptType == TubeTypes.Hesuan ? t.Pallet.HesuanTubeCount : t.Pallet.MeimianTubeCount)
                                         .FirstOrDefault()
                                     ?? PosModel.DesktopPositions.FirstOrDefault(t => t.Pallet != null && t.Pallet.Type == TubeTypes.None);

                            if (to != null)
                            {
                                var toHole = Array.IndexOf(to.Pallet.Tubes, to.Pallet.Tubes.FirstOrDefault(t => t.Type == TubeTypes.None));

                                SysModel.FrontDragTube(from, fromHole, to, toHole);
                            }
                        }
                    }
                }

                if (PosModel.DesktopPositions.Any(t => t.Pallet != null && t.Pallet.State == PalletStatus.WaitToFreezer && t.Pallet.Type == TubeTypes.Mixed))
                {
                    BeginManaulHandle(false);
                    FlowEventHelper.SendMessage(new HandoverStateChangedArgs() { Code = FlowMesssages.EmptyPalletUseUp, Detail = "无法完成分拣", Message = "空托不足,无法完成分拣操作,请补充空托" },SysModel);
                }
                #endregion

                WaitManaulHandle();

                #region 处理待合并队列

                if (PosModel.CameraToFrontPalletQueue.IsEmpty)
                {
                    var types = new[] { TubeTypes.Hesuan, TubeTypes.Meimian };
                    foreach (var type in types)
                    {
                        var positions = PosModel.DesktopPositions
                            .Where(t => t.Pallet != null && t.Pallet.State == PalletStatus.WaitToFreezer && t.Pallet.Type == type && t.Pallet.EmptyHoleCount > 0)
                            .OrderByDescending(t => t.Pallet.TubeCount).ToArray();

                        int to = 0, from = positions.Length - 1;
                        while (to < from)
                        {
                            var toHole = positions[to].GetEmptyHole();
                            var fromHole = positions[from].GetTubeHole();

                            SysModel.FrontDragTube(positions[from], fromHole, positions[to], toHole);

                            if (positions[to].Pallet.EmptyHoleCount == 0) to++;
                            if (positions[from].Pallet.TubeCount == 0) from--;
                        }
                    }
                }

                #endregion

                WaitManaulHandle();

                #region 台面 => 后处理

                if (PosModel.CameraToFrontPalletQueue.IsEmpty && PosModel.AtmToCameraPallet == null && PosModel.FreezerBeltPalletQueue.IsEmpty)
                {
                    var needCount = _taskTubeCount;
                    List<Position> gotoBackList = new List<Position>();
                    foreach (var position in PosModel.DesktopPositions)
                    {
                        if (position.Pallet == null || (position.Pallet.State != PalletStatus.WaitToTecen && position.Pallet.State != PalletStatus.WaitToAusbio && position.Pallet.State != PalletStatus.WaitToBackman)) continue;

                        if (position.Pallet.NoBarcodeCount > 0)
                        {
                            FlowEventHelper.InputBarcode(position.Pallet);
                        }
                        if (needCount == 0) break;
                        if (needCount >= position.Pallet.TubeCount)
                        {
                            needCount -= position.Pallet.TubeCount;
                            gotoBackList.Add(position);
                        }
                        else
                        {
                            Position emptyPos = PosModel.AllocEmptyPallet(SysModel);
                            while (emptyPos == null)
                            {
                                FlowEventHelper.SendMessage(new HandoverStateChangedArgs() { Code = FlowMesssages.FrontBalanceFailed, Detail = "无法完成处理", Message = "无法完成处理，请补充空托" }, SysModel);
                                emptyPos = PosModel.AllocEmptyPallet(SysModel);
                            }
                            var backCount = position.Pallet.TubeCount - needCount;
                            for (int i = 0; i < 20; i++)
                            {
                                if (position.Pallet.Tubes[i].Type == TubeTypes.None) continue;
                                SysModel.FrontDragTube(position, i, emptyPos, i);
                                backCount--;
                                needCount--;
                                if (backCount <= 0 || needCount <= 0) break;
                            }

                            if (backCount < needCount)
                            {
                                emptyPos.Pallet.State = PalletStatus.WaitToFreezer;
                                gotoBackList.Add(position);
                            }
                            else
                            {
                                emptyPos.Pallet.State = position.Pallet.State;
                                position.Pallet.State = PalletStatus.WaitToFreezer;
                                gotoBackList.Add(emptyPos);
                            }
                        }


                    }

                    //排序
                    var tubes = gotoBackList.SelectMany(t => t.Pallet.Tubes).Where(t => t.Type != TubeTypes.None).OrderBy(t => Array.IndexOf(new[] { "A","O","B","AB"},t.BloodType)).ToList();
                    tubes.ForEach(t => t.Stripindex = tubes.IndexOf(t));

                    foreach (var gotoback in gotoBackList)
                    {
                        SysModel.Atm.CrossingDamBoard.StartRecede();
                        SysModel.Atm.CrossingPushrod.StartRecede();
                        SysModel.FrontDragPallet(gotoback, PosModel.AtmBeltPosition);
                        SysModel.Atm.Belt.StartRecede();
                        while (!SysModel.Atm.CrossingPushrodSensor.IsActive() || SysModel.Atm.CrossingPushrodSafeSensor.IsActive())
                        {
                            Thread.Sleep(10);
                        }
                        SysModel.Atm.Belt.Stop();
                        SysModel.Atm.CrossingPushrod.StartForward();
                        SysModel.Atm.CrossingPushrod.WaitCompleted();
                        PosModel.FrontToBackQueue.Enqueue(PosModel.AtmBeltPosition.Pallet);
                        PosModel.AtmBeltPosition.Pallet = null;
                    }
                }

                #endregion

                WaitManaulHandle();

                #region 台面 => 冷藏

                if (_freezerLock.WaitOne(0))
                {
                    if (PosModel.FreezerBeltPalletQueue.IsEmpty
                        && PosModel.CameraToFrontPalletQueue.IsEmpty
                        && PosModel.FreezerBeltPosition.Pallet == null
                        && PosModel.FreezerPositions.All(a => a.All(t => t.State != PalletStatus.WaitToAusbio && t.State != PalletStatus.WaitToTecen && t.State != PalletStatus.WaitToBackman && t.State != PalletStatus.WaitToDesktop)))
                    {
                        var position = PosModel.DesktopPositions.Where(t => t.Pallet != null && t.Pallet.TubeCount > 0).OrderByDescending(t => t.Pallet.TubeCount).FirstOrDefault(t => t.Pallet != null && t.Pallet.State == PalletStatus.WaitToFreezer && t.Pallet.Type != TubeTypes.Mixed);

                        if (position != null)
                        {
                            var targetAisle = PosModel.AllocFreezerAisleForIn(position.Pallet.Type);
                            if (targetAisle >= 0)
                            {
                                if (PosModel.FreezerPositions[targetAisle].Count == 0 || PosModel.FreezerPositions[targetAisle].Peek().TubeCount == 20)
                                {
                                    SysModel.FrontDragPallet(position, PosModel.FreezerBeltPosition);
                                }
                                else
                                {
                                    PosModel.FreezerPositions[targetAisle].Peek().State = PalletStatus.WaitToDesktop;
                                }
                            }
                        }
                    }
                    _freezerLock.Set();
                }

                #endregion

                WaitManaulHandle();

                #region 交接处理完事件

                if (PosModel.DesktopPositions.All(t => t.Pallet == null || (t.Pallet.State != PalletStatus.WaitBalance && t.Pallet.State != PalletStatus.WaitScanBarcode)))
                {
                    // TODO: 通知ATM当前交接单处理完
                    //  CurrentHandoverId = null;
                }

                #endregion
            }
        }



        private int _taskTubeCount = 40;
        private int _dealCount = 0;
        private int _strip = 0;
        private int _stripindex = 0;

        //类型以及数量
        private void BackTask()
        {
            //阳普不用转角度
            while (IsRunning)
            {
                if (PosModel.FrontToBackQueue.IsEmpty) continue;

                if (SysModel.Back.BeltEndSensor.IsActive())
                {
                    // 打开抽风
                    SysModel.Back.Laminar.TurnOn();

                    Pallet pallet;
                    PosModel.FrontToBackQueue.TryDequeue(out pallet);
                    PosModel.BackBeltPosition.Pallet = pallet;


                    Tube tube = new Tube();
                    T_Sample sample = new T_Sample();

                    for (int i = 19; i >= 0; i--)
                    {
                       // SysModel.Back.Belt.Stop();
                        if (pallet.Tubes[i].Type == TubeTypes.None)
                        {
                            continue;
                        }
                        while (!SysModel.Back.Uncap.CanDropIn())
                        {
                            if (SysModel.Back.Uncap.CanDragOut())
                            {
                                tube = SysModel.Back.Uncap.DequeueOne();
                                _strip = stripExists[tube.Stripindex / stripLength];
                                _stripindex = tube.Stripindex % stripLength;
                                SysModel.BackDragTube(PosModel.DialOutPosition, 0, currentPositions[_strip], _stripindex, doAfterDrag: () =>
                                {
                                    SysModel.Back.Uncap.Start();
                                });

                                IDatatoFlow.InsertSampleHistory(new T_HistorySample
                                {
                                    Id = Guid.NewGuid().ToString("N"),
                                    SampleId = tube.Id,
                                    Time = DateTime.Now,
                                    Remark = "插入载条"
                                });
                                //更新试管状态
                                sample = new T_Sample()
                                {
                                    Id = tube.Id,
                                    PostionId = currentPositions[_strip].Id,
                                    Index = _stripindex,
                                    State = 2,
                                    Is_Delete = true,
                                    ReBarCode = "",
                                };
                                IDatatoFlow.SampleUpdate(sample);

                                IDatatoFlow.InsertSampleHistory(new T_HistorySample
                                {
                                    Id = Guid.NewGuid().ToString("N"),
                                    SampleId = tube.Id,
                                    Time = DateTime.Now,
                                    Remark = "执行开盖"
                                });
                            }
                            else
                            {
                                SysModel.Back.Uncap.Start();
                            }   
                        }
                        SysModel.BackDragTube(PosModel.BackBeltPosition, i, PosModel.DialInPosition, 0);
                            SysModel.Back.Uncap.EnqueueOne(PosModel.BackBeltPosition.Pallet.Tubes[i]);
                        PosModel.BackBeltPosition.Pallet.Tubes[i] = Tube.Empty;
                        _dealCount++;
                    }

                    SysModel.BackCollectPallet(PosModel.BackBeltPosition, PosModel.CollectPosition);

                    if (_dealCount >= _taskTubeCount)
                    {
                        while (!SysModel.Back.Uncap.IsEmpty)
                        {
                            if (SysModel.Back.Uncap.CanDragOut())
                            {
                                tube = SysModel.Back.Uncap.DequeueOne();
                                _strip = stripExists[tube.Stripindex / stripLength];
                                _stripindex = tube.Stripindex % stripLength;
                                SysModel.BackDragTube(PosModel.DialOutPosition, 0, currentPositions[_strip], _stripindex, doAfterDrag: () =>
                                {
                                    SysModel.Back.Uncap.Start();
                                });

                                IDatatoFlow.InsertSampleHistory(new T_HistorySample
                                {
                                    Id = Guid.NewGuid().ToString("N"),
                                    SampleId = tube.Id,
                                    Time = DateTime.Now,
                                    Remark = "插入载条"
                                });
                                //更新试管状态
                                sample = new T_Sample()
                                {
                                    Id = tube.Id,
                                    PostionId = currentPositions[_strip].Id,
                                    Index = _stripindex,
                                    State = 2,
                                    Is_Delete = true,
                                    ReBarCode = "",
                                };
                                IDatatoFlow.SampleUpdate(sample);

                                IDatatoFlow.InsertSampleHistory(new T_HistorySample
                                {
                                    Id = Guid.NewGuid().ToString("N"),
                                    SampleId = tube.Id,
                                    Time = DateTime.Now,
                                    Remark = "执行开盖"
                                });
                            }
                            else
                            {
                                SysModel.Back.Uncap.Start();
                            }
                        }

                        //更新任务记录
                        T_Task task = new T_Task()
                        {
                            Id = _taskId,
                            State = "任务完成"
                        };
                        IDatatoFlow.TaskUpdate(task);
                        _dealCount = 0;

                        // 关闭抽风
                        SysModel.Back.Laminar.TurnOff();
                        _IsTaskOk = true;
                        SpeechHelper.SpeekAynsc("任务已完成!任务已完成!任务已完成!");
                    }
                }
                else
                {
                    SysModel.Back.Belt.StartForward();
                }
            }
        }

        #endregion

        private int[] _xFirstHoles = { 0, 3, 4, 8, 9 };
        private int[] _yFirstHoles = { 1, 5 };

        private AutoResetEvent _handleLock = new AutoResetEvent(true);


        public void InitData(PalletStatus state)
        {
            switch (state)
            {
                case PalletStatus.WaitToAusbio:
                    stripLength = 32;
                    currentPositions = PosModel.AusbioPositions;
                    for (int i = 0; i < SysModel.Back.AusbioSersors.Length; i++)
                    {
                        var sensor = SysModel.Back.AusbioSersors[i];
                        if (sensor.IsActive())
                        {
                            stripExists.Add(i);
                        }
                    }
                    break;
                case PalletStatus.WaitToTecen:
                    stripLength = 16;
                    currentPositions = PosModel.TecanPositions;
                    for (int i = 0; i < SysModel.Back.TecanSersors.Length; i++)
                    {
                        var sensor = SysModel.Back.TecanSersors[i];
                        if (sensor.IsActive())
                        {
                            stripExists.Add(i);
                        }
                    }
                    break;
                case PalletStatus.WaitToBackman:
                    stripLength = 10;
                    currentPositions = PosModel.BackManPositions;
                    for (int i = 0; i < SysModel.Back.BackManSersors.Length; i++)
                    {
                        var sensor = SysModel.Back.BackManSersors[i];
                        if (sensor.IsActive())
                        {
                            stripExists.Add(i);
                        }
                    }
                    break;
            }
        }

        int stripLength = 0;
        Position[] currentPositions = new Position[] { };
        private List<int> stripExists = new List<int>();
        private int BeginHandle(string _taskId, int tubeType, int expectCount, PalletStatus state)
        {
            this._taskId = _taskId;
            var ec = expectCount;
            _freezerLock.WaitOne();
            stripExists.Clear();
            _IsTaskOk = false;
            switch (state)
            {
                case PalletStatus.WaitToAusbio:
                    stripLength = 32;
                    currentPositions = PosModel.AusbioPositions;
                    for (int i = 0; i < SysModel.Back.AusbioSersors.Length; i++)
                    {
                        var sensor = SysModel.Back.AusbioSersors[i];
                        if (sensor.IsActive())
                        {
                            stripExists.Add(i);
                        }
                    }
                    break;
                case PalletStatus.WaitToTecen:
                    stripLength = 16;
                    currentPositions = PosModel.TecanPositions;
                    for (int i = 0; i < SysModel.Back.TecanSersors.Length; i++)
                    {
                        var sensor = SysModel.Back.TecanSersors[i];
                        if (sensor.IsActive())
                        {
                            stripExists.Add(i);
                        }
                    }
                    break;
                case PalletStatus.WaitToBackman:
                    stripLength = 10;
                    currentPositions = PosModel.BackManPositions;
                    for (int i = 0; i < SysModel.Back.BackManSersors.Length; i++)
                    {
                        var sensor = SysModel.Back.BackManSersors[i];
                        if (sensor.IsActive())
                        {
                            stripExists.Add(i);
                        }
                    }
                    break;
            }

            if (tubeType == (int)TubeTypes.Meimian)
            {
                var pallets = PosModel.FreezerPositions.SelectMany(t => t).Where(t => t.Type == TubeTypes.Meimian).OrderBy(t => t.MinGatherTime).ToArray();
                foreach (var pallet in pallets)
                {
                    pallet.State = state;
                    expectCount -= pallet.TubeCount;
                    if (expectCount <= 0)
                    {
                        expectCount = 0;
                        break;
                    }
                }
            }
            else
            {
                var pallets = PosModel.FreezerPositions.SelectMany(t => t).Where(t => t.Type == TubeTypes.Hesuan).OrderBy(t => t.MinGatherTime).ToArray();
                foreach (var pallet in pallets)
                {
                    if (pallet.Tubes.All(t => !t.State.HasFlag(TubeStatus.Checked))) continue;

                    var checkedCount = pallet.Tubes.Count(t => t.State == TubeStatus.Checked);
                    var positiveCount = pallet.Tubes.Count(t => t.State > TubeStatus.Checked);

                    if (expectCount > 0)
                    {
                        expectCount -= checkedCount;
                        pallet.State = state;
                    }
                    else if (positiveCount > 0)
                    {
                        // TODO: 有bug 要改
                        pallet.State = PalletStatus.WaitToDesktop;
                    }
                }
            }
            _freezerLock.Set();

            return ec + expectCount;
        }

    }
}
